package org.lpw.wormhole.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.util.EntityUtils;

/**
 * @author lpw
 */
public class HttpImpl
    implements Http
{
    protected final Kit kit;
    protected final ExecutorService threadPool;
    protected final HttpRequestInterceptor requestInterceptor;
    protected final HttpResponseInterceptor responseInterceptor;

    public HttpImpl(Kit kit)
    {
        super();

        this.kit = kit;
        threadPool = Executors.newFixedThreadPool(kit.getConfigurer().getHttpMaxThread());
        requestInterceptor = new HttpGzipInterceptor();
        responseInterceptor = new HttpGzipInterceptor();
    }

    @Override
    public void put(String[] urls, final Map<String, String> parameters)
    {
        if(urls==null||urls.length==0)
            return;

        for(final String url : urls)
        {
            threadPool.execute(new Runnable()
            {
                @Override
                public void run()
                {
                    post(url, parameters);
                }
            });
        }
    }

    @Override
    public String get(String[] urls, final Map<String, String> parameters)
    {
        if(urls==null||urls.length==0)
            return null;

        final List<String> list = new ArrayList<String>();
        for(final String url : urls)
        {
            threadPool.execute(new Runnable()
            {
                @Override
                public void run()
                {
                    list.add(post(url, parameters));
                }
            });
        }

        try
        {
            for(; true;)
            {
                Thread.sleep(1L);

                if(list.isEmpty())
                    continue;

                for(String content : list)
                    if(content!=null)
                        return content;

                if(list.size()==urls.length)
                    return null;
            }
        }
        catch(InterruptedException e)
        {
            kit.getLogger().warn(e, "等待HTTP请求结果时发生异常！");

            return null;
        }
    }

    protected String post(String url, Map<String, String> parameters)
    {
        HttpClient client = newHttpClient();
        try
        {
            HttpPost post = new HttpPost(url);
            if(parameters!=null&&!parameters.isEmpty())
            {
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for(String key : parameters.keySet())
                    nvps.add(new BasicNameValuePair(key, parameters.get(key)));
                post.setEntity(new UrlEncodedFormEntity(nvps));
            }

            String content = EntityUtils.toString(client.execute(post).getEntity());
            client.getConnectionManager().shutdown();

            return content;
        }
        catch(Exception e)
        {
            kit.getLogger().warn(e, "使用POST获取URL["+url+"]数据时发生异常！");

            return null;
        }
    }

    protected HttpClient newHttpClient()
    {
        DefaultHttpClient client = new DefaultHttpClient();
        client.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, kit.getConfigurer().getHttpConnectionTimeout()*1000);
        client.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, kit.getConfigurer().getHttpReadTimeout()*1000);
        client.addRequestInterceptor(requestInterceptor);
        client.addResponseInterceptor(responseInterceptor);

        return client;
    }

    @Override
    public void destory()
    {
        threadPool.shutdown();
    }
}
